package com.wgchao.identityrightsmanagement.application.service;

import com.wgchao.identityrightsmanagement.domain.organization.repository.*;
import com.wgchao.identityrightsmanagement.domain.organization.model.*;
import com.wgchao.identityrightsmanagement.infrastructure.exception.ObjectDisabledException;
import com.wgchao.identityrightsmanagement.infrastructure.exception.ObjectNotExistException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;

/**
 * @ClassName: DepartmentApplicationService
 * @author: wgchao
 * @createTime: 2020/6/8 10:12 AM
 * @Description: 应用服务-部门
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class DepartmentApplicationService {
    @Autowired
    private AgencyRepository agencyRepository;
    @Autowired
    private DepartmentRepository departmentRepository;
    @Autowired
    private AssignOfficeToDepartmentService assignOfficeToDepartmentService;
    @Autowired
    private OfficeRepository officeRepository;
    @Autowired
    private DepartmentOfficeRepository departmentOfficeRepository;
    @Autowired
    private AssignDepartmentToAccountService assignDepartmentToAccountService;
    @Autowired
    private AccountRepository accountRepository;
    @Autowired
    private ApplicationEventPublisher publisher;

    // 添加新部门
    public void addDepartment(String agencyCode, DepartmentCreator departmentCreator, String operator){
        Agency agency = agencyRepository.findById(agencyCode);
        if(agency == null){
            throw new ObjectNotExistException("机构不存在");
        }
        String departmentCode = departmentRepository.generateCode(agencyCode);
        Department department = Department.addDepartment(agency, departmentCode, departmentCreator);
        departmentRepository.add(department, operator);
    }

    /**
     * 修改部门的基本信息
     * @param code
     * @param departmentUpdator
     * @param operator
     */
    public void modifyDepartmentInfo(String code, DepartmentUpdator departmentUpdator, String operator){
        Department department = departmentRepository.findById(code);
        if(department == null){
            throw new ObjectNotExistException("部门不存在");
        }
        Agency agency = agencyRepository.findById(department.getAgencyCode());
        if(agency == null){
            throw new ObjectNotExistException("机构不存在");
        }
        department.modifyDepartmentInfo(departmentUpdator, agency);
        departmentRepository.add(department, operator);
    }

    /**
     * 停用部门
     * @param code
     * @param operator
     */
    public void disable(String code, String operator){
        Department department = departmentRepository.findById(code);
        if(department == null){
            throw new ObjectNotExistException("部门不存在");
        }
        department.disable();
        departmentRepository.add(department, operator);
    }

    /**
     * 启用部门
     * @param code
     * @param operator
     */
    public void regain(String code, String operator){
        Department department = departmentRepository.findById(code);
        if(department == null){
            throw new ObjectNotExistException("部门不存在");
        }
        department.regain();
        departmentRepository.add(department, operator);
    }

    public void remove(String code, String operator){
        Department department = departmentRepository.findById(code);
        if(department == null){
            throw new ObjectNotExistException("部门不存在");
        }
        departmentRepository.remove(department, operator);

        // 发布部门删除事件  重置部门账户、清除部门职位关系、清除账户部门职位关系、清除部门职位权限
        publisher.publishEvent(new DepartmentRemovedEvent(new Date(), code, department.getAgencyCode(), operator));
    }

    // 为部门分配职位
    public void assignOfficesToDepartment(List<String> officeCodes, String departmentCode, String operator){
        Department department = departmentRepository.findById(departmentCode);
        if(department == null){
            throw new ObjectNotExistException("部门不存在");
        }
        if(!department.normal()){
            throw new ObjectDisabledException(department.getName()+"部门不可用");
        }
        //删除原有的职位信息
        departmentOfficeRepository.deleteAllByDepartment(departmentCode);

        for(String officeCode : officeCodes){
            Office office = officeRepository.findById(officeCode);
            if(office == null){
                throw new ObjectNotExistException("职位不存在");
            }
            if(!office.normal()){
                throw new ObjectDisabledException(office.getName()+"职位不可用");
            }
            DepartmentOffice departmentOffice = assignOfficeToDepartmentService
                    .assignOfficeToDepartment(departmentOfficeRepository.generateCode(), department, office);
            departmentOfficeRepository.add(departmentOffice, operator);
        }

        //发布事件 重新检查部门职位关系
        System.out.println("发布事件 重新检查部门职位关系");
        publisher.publishEvent(new AssignedOfficesToDepartmentEvent(new Date(), departmentCode, officeCodes, operator));
    }

    /**
     * 部门删除 删除部门职位关系
     * @param departmentRemovedEvent
     */
    @EventListener
    public void removeDO(DepartmentRemovedEvent departmentRemovedEvent) {
        List<DepartmentOffice> departmentOffices = departmentOfficeRepository
                .findByDepartment(departmentRemovedEvent.getDepartmentCode());
        if(departmentOffices != null){
            departmentOfficeRepository.removeAll(departmentOffices, departmentRemovedEvent.getOperator());
        }
    }

    /**
     * 职位删除 删除部门职位关系
     * @param officeRemoveEvent
     */
    @EventListener
    public void removeDO(OfficeRemovedEvent officeRemoveEvent) {
        List<DepartmentOffice> departmentOffices = departmentOfficeRepository
                .findByOffice(officeRemoveEvent.getOfficeCode());
        if(departmentOffices != null){
            departmentOfficeRepository.removeAll(departmentOffices, officeRemoveEvent.getOperator());
        }
    }

}
